/*
 * JSFConsole - Lightweight JSF Application Monitor
 * Copyright (C) 2009  Grzegorz Bugaj
 * http://www.gregbugaj.com
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
package com.gregbugaj.reflector.renderer;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.gregbugaj.jsfconsole.enums.NodeType;
import com.gregbugaj.jsfconsole.util.XMLUtil;
import com.gregbugaj.reflector.visitors.JSFDumpContext;
/**
 * Abstract renderer class
 * @author devil
 *
 */
public abstract class AbstractRenderer {
	private final StringBuffer buffer;
	private JSFDumpContext context;
	public AbstractRenderer(){
		buffer = new StringBuffer();
	}

	public void render(JSFDumpContext context) throws Exception{
		this.context=context;
		render(context.getDocument());
	}
/*
	public void render(String xmlstring) throws Exception{
		Document doc = XMLUtil.getXmlDocument(new ByteArrayInputStream(xmlstring.getBytes("UTF-8")));
		render(doc);
	}
*/
	private void render(Document xmldocument) throws Exception{
		NodeList top = XMLUtil.extract("/instance/*", xmldocument);
		emit(top.item(0), null);
	}


	protected  void emit(Node root, EmitContext context) throws Exception{
		//Create new emitiing context with all properties enabled
		if(context==null){
			context=new EmitContext();
		}
		
		String nodeName="null";
		if(root!=null){
			nodeName=root.getNodeName();
		}
		
		final NodeType type=NodeType.fromValue(nodeName);
		
		switch(type){
		case NULL : emitField(makeNullNode(), context); break;
		case OBJECT : emitObject(root, context); break;
		case FIELD : emitField(root, context); break;
		case COLLECTION : emitCollectionField(root, context); break;
		case ARRAY : emitArrayField(root, context); break;
		case REFERENCE : emitReference(root, context); break;
		case MAP: emitMap(root, context); break;
		case METHOD: emitMethod(root, context); break;
				
		default : emitObject(root, context); break;
		}

	}
	/**
	 * Create a node that represents a Null object
	 * @return node with set null attributes
	 */
	private Node makeNullNode() {
		Document doc=context.getDocument();
		Element node=doc.createElement("NULL");
		
		Attr nameAttr=doc.createAttribute("name");
		nameAttr.setValue("");
		node.setAttributeNode(nameAttr);
		
		Attr typeAttr=doc.createAttribute("type");
		typeAttr.setValue("NULLREF");
		node.setAttributeNode(typeAttr);
		
		
		Attr valueAtr=doc.createAttribute("value");
		valueAtr.setValue("null");
		node.setAttributeNode(valueAtr);
		
		return node;
	}

	/**
	 * Append Objects toString to the end of the  buffer
	 * @param o
	 */
	protected  void c(Object o) {
		buffer.append(o);
	}

	public StringBuffer getBuffer() {
		return buffer;
	}

	public String getBufferToString() {
		String retValue="";
		if(buffer!=null){
			retValue=buffer.toString();
		}
		return retValue;
	}


	/**
	 * 
	 * @param node
	 * @param context 
	 * @throws Exception
	 */
	protected abstract void emitObject(Node node, EmitContext context) throws Exception;
	/**
	 * 
	 * @param node
	 * @param context 
	 * @throws Exception
	 */
	protected abstract void emitArrayField(Node node, EmitContext context) throws Exception;
	/**
	 * 
	 * @param node
	 * @param context 
	 * @throws Exception
	 */
	protected abstract void emitCollectionField(Node node, EmitContext context)	throws Exception ;
	/**
	 * 
	 * @param node
	 * @param context 
	 * @throws Exception
	 */
	protected abstract void emitMethod(Node node, EmitContext context) throws Exception ;
	/**
	 * 
	 * @param node
	 * @param context 
	 * @throws Exception
	 */
	protected abstract void emitMap(Node node, EmitContext context) throws Exception ;
	/**
	 * 
	 * @param node
	 * @param context 
	 * @throws Exception
	 */
	protected abstract void emitReference(Node node, EmitContext context) throws Exception ;
	/**
	 * 
	 * @param node
	 * @param context 
	 * @throws Exception
	 */
	protected abstract void emitField(Node node, EmitContext context) throws Exception ;

}

